package com.yong.activemq.queue;

import org.apache.activemq.ActiveMQConnectionFactory;

import javax.jms.*;
import java.io.IOException;

public class JmsConsumer {
    static final String DEFAULT_URL = "tcp://localhost:61616";
    static final String QUEUE_NAME = "queue-01";

    /**
     * 点对点消息传递域的特点如下：
     * （1）每个消息只能有一个消费者，类似1对1的关系。好比个人快递自己领取自己的
     * （2）消息的生产者和消费者之间没有时间上的相关性。
     *    无论消费者在生产者发送消息的时候是否处于运行状态，消费者都可以提取消息。
     *    好比我们的发送短信，发送者发送后不见得接收者会既收既看。
     * （3）消息被消费后队列中不会再存储，所以消费者不会消费到已经被消费掉的消息。
     * @param args
     * @throws JMSException
     */
    public static void main(String[] args) throws JMSException, IOException {

        System.out.println("我是2号消费者");

        // 1、创建连接工厂
        ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(DEFAULT_URL);

        // 2、通过连接工厂创建connection，并且启动连接
        Connection connection = activeMQConnectionFactory.createConnection();
        connection.start();

        // 3、通过connection创建session
        // 第一个参数：事务； 第二个参数：签收
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

        // 4、通过session创建destination；首先采用queue
        Queue queue = session.createQueue(QUEUE_NAME);

        // 5、通过session创建consumer消费者
        MessageConsumer messageConsumer = session.createConsumer(queue);

        /*
        第一种访问方式：
        同步阻塞方式（receive()）
        订阅者或接收者调用messageConsumer的receive()方法来接收消息，receive方法在能够接收到消息之前(或超时之前)将一直阻塞.

        //记住：发送的是什么格式，自然接收的格式也要跟发送的格式一样
        while(true) {
            //不带时间的receive()方法，说明这方法一直在等待新消息。
            //TextMessage receive = (TextMessage) messageConsumer.receive();
            //带时间的receive()方法，说明该方法一旦到了时间就立刻结束接收。
            TextMessage receive = (TextMessage) messageConsumer.receive(5000L);

            if (receive != null){
                System.out.println("消费到内容："+receive.getText());
            }else{
                break;
            }

        }

        // 关闭所有连接
        messageConsumer.close();
        session.close();
        connection.close();*/


        /**
         *   第二种访问方式：
         *      能够解决消费者的监听，通过监听的方式消费消息
         */
        messageConsumer.setMessageListener(new MessageListener() {
            @Override
            public void onMessage(Message message) {
                if (null != message && message instanceof TextMessage) {
                    TextMessage textMessage = (TextMessage) message;
                    try {
                        System.out.println("****消费者接收到消息:" + textMessage.getText());
                    } catch (JMSException e) {
                        e.printStackTrace();
                    }
                }
            }
        });

        System.in.read();  //保证控制台不关
        messageConsumer.close();
        session.close();
        connection.close();
    }
}

/**
 * 消息的三种案例：
 *
 * 1.先生产，只启动1号消费者。问题：1号消费者能消费消息吗？ yes
 *
 * 2.先生产，先启动1号消费者再启动2号消费者，问题：2号消费者还能消费消息吗？
 *  2.1 1号可以消费吗？  yes
 *  2.2 2号可以消费吗？ NO
 *
 * 3.先启动2个消费者，再生产6条消息，请问，消费情况如何？
 *   3.1 2个消费者都有6条
 *   3.2 先到先得  6条全部给一个
 *   3.3 一人一半   yes
 *
 *   消息中间件有点像负载均衡轮询思想，若有两个接收者就一人一个消息，直到最后没有消息，就平均分
 */
